package com.sky.service.impl;

import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private WorkspaceService workspaceService;

    /**
     * 营业额统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        //拼接日期集合
        StringBuilder dateList = new StringBuilder();
        List<LocalDate> dates = new ArrayList<>();
        while (!begin.isEqual(end.plusDays(1))) {
            dateList.append(begin).append(begin.isEqual(end) ? "" : ",");
            dates.add(begin);
            begin = begin.plusDays(1);
        }
        log.info("拼接出来的日期集合为：{}", dateList);

        //查询每日营业额拼接位集合
        StringBuilder turnoverList = new StringBuilder();
        for (int i = 0; i < dates.size(); i++) {
            Double turnover = orderMapper.getTurnoverByDate(dates.get(i), Orders.COMPLETED);
            turnoverList.append(turnover == null ? 0 : turnover).append(i == dates.size() - 1 ? "" : ",");
        }
        log.info("拼接出来的每日营业额集合为：{}", turnoverList);
        return new TurnoverReportVO(dateList.toString(), turnoverList.toString());
    }

    /**
     * 用户数据统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        //拼接日期集合
        StringBuilder dateList = new StringBuilder();
        List<LocalDate> dates = new ArrayList<>();
        while (!begin.isEqual(end.plusDays(1))) {
            dateList.append(begin).append(begin.isEqual(end) ? "" : ",");
            dates.add(begin);
            begin = begin.plusDays(1);
        }
        log.info("拼接出来的日期集合为：{}", dateList);

        // 使用一个HashMap缓存已查询的日期的totalUser值
        Map<LocalDate, Integer> totalUserCache = new HashMap<>();
        StringBuilder newUserList = new StringBuilder();
        StringBuilder totalUserList = new StringBuilder();
        for (int i = 0; i < dates.size(); i++) {
            //获取每天当天总的用户数
            LocalDate today = dates.get(i);
            Integer totalUser = userMapper.selectTotalUser(today);
            totalUser = totalUser == null ? 0 : totalUser;
            totalUserList.append(totalUser).append(i == dates.size() - 1 ? "" : ",");
            totalUserCache.put(today, totalUser);
        }
        //获取每天的新增用户数即今天的减去昨天的
        //获取第一天的前一天的用户数
        Integer lastDayUser = userMapper.selectTotalUser(dates.get(0).minusDays(1));
        lastDayUser = lastDayUser == null ? 0 : lastDayUser;
        totalUserCache.put(dates.get(0).minusDays(1), lastDayUser);
        for (int i = 0; i < dates.size(); i++) {
            LocalDate today = dates.get(i);
            Integer newUser = totalUserCache.get(today) - totalUserCache.get(today.minusDays(1));
            newUserList.append(newUser).append(i == dates.size() - 1 ? "" : ",");
        }

        log.info("拼接出来的新增用户集合和用户总数集合为：{},{}", newUserList, totalUserList);
        return new UserReportVO(dateList.toString(), totalUserList.toString(), newUserList.toString());
    }

    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        //拼接日期集合
        StringBuilder dateList = new StringBuilder();
        List<LocalDate> dates = new ArrayList<>();
        while (!begin.isEqual(end.plusDays(1))) {
            dateList.append(begin).append(begin.isEqual(end) ? "" : ",");
            dates.add(begin);
            begin = begin.plusDays(1);
        }
        log.info("拼接出来的日期集合为：{}", dateList);

        // 使用一个HashMap缓存已查询的日期的orderCount值
        Map<LocalDate, Integer> totalUserCache = new HashMap<>();
        StringBuilder orderCountList = new StringBuilder();
        StringBuilder validOrderCountList = new StringBuilder();

        Integer totalOrderCounts = 0;
        Integer validOrderCounts = 0;
        //获取每天的订单总数,拼接成字符串,获取有效订单数，拼接成字符串
        for (int i = 0; i < dates.size(); i++) {
            LocalDate today = dates.get(i);
            Integer orderCount = orderMapper.getOrderCountByDate(today, -1);
            orderCount = orderCount == null ? 0 : orderCount;
            totalUserCache.put(today, orderCount);
            orderCountList.append(orderCount).append(i == dates.size() - 1 ? "" : ",");
            totalOrderCounts += orderCount;


            Integer validOrderCount = orderMapper.getOrderCountByDate(today, Orders.COMPLETED);
            validOrderCount = validOrderCount == null ? 0 : validOrderCount;
            validOrderCountList.append(validOrderCount).append(i == dates.size() - 1 ? "" : ",");
            validOrderCounts += validOrderCount;
        }

        Double orderCompletionRate = ((double) validOrderCounts / (double) totalOrderCounts);
        return new OrderReportVO(dateList.toString(), orderCountList.toString(), validOrderCountList.toString(), totalOrderCounts, validOrderCounts, orderCompletionRate);
    }

    /**
     * 查询销量排名top10
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO top10Report(LocalDate begin, LocalDate end) {
        //用一个Map集合存储名字和销量数据
        Map<String, Integer> dishSales = new HashMap<>();
        //查询这个时间段所有的订单
        List<Orders> ordersList = orderMapper.queryOrderByTimePeriod(begin, end, Orders.COMPLETED);
        //遍历订单的集合来查询订单的详细表，用Map集合存储菜品名字和份数
        for (Orders order : ordersList) {
            for (OrderDetail orderDetail : orderDetailMapper.getDetailsByOrderId(order.getId())) {
                String dishName = orderDetail.getName();
                Integer dishNumber = orderDetail.getNumber();
                if (dishSales.get(dishName) == null) {
                    dishSales.put(dishName, dishNumber);
                } else {
                    dishSales.put(dishName, dishSales.get(dishName) + dishNumber);
                }
            }
        }

        //遍历Map集合来拼接名字和销量的字符串
        List<Map.Entry<String, Integer>> entryList = dishSales.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) // 按值进行降序排序
                .limit(10) // 只保留前十个元素
                .collect(Collectors.toList());

        StringBuilder nameList = new StringBuilder();
        StringBuilder numberList = new StringBuilder();
        for (int i = 0; i < entryList.size(); i++) {
            Map.Entry<String, Integer> entry = entryList.get(i);
            if (entry != null) {
                String dishName = entry.getKey();
                Integer salesCount = entry.getValue();
                if (dishName != null && salesCount != null) {
                    nameList.append(dishName).append(i == entryList.size() - 1 ? "" : ",");
                    numberList.append(salesCount).append(i == entryList.size() - 1 ? "" : ",");
                }
            }
        }
        log.info("拼接出来的销量的前十的名字是：{}", nameList);
        log.info("拼接出来的销量的前十的销量是：{}", numberList);
        return new SalesTop10ReportVO(nameList.toString(), numberList.toString());
    }

    @Override
    public void exportBusinessExcelReport(HttpServletResponse response) {
        //获取工作台的30天的相关报表数据

        LocalDateTime endTime = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MAX);
        LocalDateTime beginTime = LocalDateTime.of(LocalDate.now().minusDays(30), LocalTime.MIN);

        BusinessDataVO businessData = workspaceService.getBusinessData(beginTime, endTime);
        log.info("获取到的30天的相关报表数据：{}", businessData);
        //把数据写入excel文件
        //用反射得到模版文件
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
        try {
            //生成excel对象
            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
            //获取第一页
            XSSFSheet sheet1 = excel.getSheetAt(0);
            //获取第二行
            XSSFRow row2 = sheet1.getRow(1);
            //获取第二行的第二个单元格，用于存储表的时间信息
            row2.getCell(1).setCellValue(beginTime.toLocalDate() + " 至 " + endTime.toLocalDate());

            //获取第四行，第五行写入相应的数据
            XSSFRow row3 = sheet1.getRow(3);
            row3.getCell(2).setCellValue(businessData.getTurnover());
            row3.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row3.getCell(6).setCellValue(businessData.getNewUsers());

            XSSFRow row4 = sheet1.getRow(4);
            row4.getCell(2).setCellValue(businessData.getValidOrderCount());
            row4.getCell(4).setCellValue(businessData.getUnitPrice());


            //写入表格的下半部分的数据
            for (int i = 0; i < 30; i++) {
                LocalDate begin = beginTime.toLocalDate();
                LocalDate date = begin.plusDays(i);
                LocalDateTime newDate = LocalDateTime.of(date, LocalTime.MIN);
                BusinessDataVO businessDataForDay = workspaceService.getBusinessData(newDate, newDate);
                XSSFRow row = sheet1.getRow(7 + i);
                row.getCell(1).setCellValue(date.toString());
                row.getCell(2).setCellValue(businessDataForDay.getTurnover());
                row.getCell(3).setCellValue(businessDataForDay.getValidOrderCount());
                row.getCell(4).setCellValue(businessDataForDay.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessDataForDay.getUnitPrice());
                row.getCell(6).setCellValue(businessDataForDay.getNewUsers());


            }
            //进行文件的下载
            ServletOutputStream outputStream = response.getOutputStream();
            excel.write(outputStream);

            //资源的关闭
            outputStream.flush();
            outputStream.close();
            excel.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
